package com.zx.zxpicture.domain.picture.template;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.CIObject;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import com.qcloud.cos.model.ciModel.persistence.ProcessResults;
import com.zx.zxpicture.infrstructure.common.ErrorCode;
import com.zx.zxpicture.infrstructure.config.CosClientConfig;
import com.zx.zxpicture.infrstructure.exception.BusinessException;
import com.zx.zxpicture.infrstructure.manager.CosManager;
import com.zx.zxpicture.interfaces.dto.picture.UploadPictureResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

@Slf4j
public abstract class PictureUploadTemplate {
    @Resource
    private CosManager cosManager;
    @Resource
    private CosClientConfig cosClientConfig;
    /**
     * 校验图片
     * @param inputSource
     * @param <T>
     */
    public abstract <T> void validPicture(T inputSource);

    /**
     * 获取原始图片名
     * @param inputSource
     * @return
     * @param <T>
     */
    public abstract <T> String getFileName(T inputSource);

    /**
     * 图片写入文件
     * @param inputSource 输入方式
     * @param file 要写入图片的文件
     * @param <T> 输入方式类型
     */
    public abstract <T> void getFile(T inputSource , File file);

    /**
     * 封装原始图片返回结果
     * 这个是没有封装缩略图字段的
     * 前端做了处理，如果没有缩略图就访问url字段
     */
    private UploadPictureResult buildResult(String originFilename, File file, String uploadPath, ImageInfo imageInfo) {
        UploadPictureResult uploadPictureResult = new UploadPictureResult();
        int picWidth = imageInfo.getWidth();
        int picHeight = imageInfo.getHeight();
        double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();
        uploadPictureResult.setPicName(FileUtil.mainName(originFilename));
        uploadPictureResult.setPicWidth(picWidth);
        uploadPictureResult.setPicHeight(picHeight);
        uploadPictureResult.setPicScale(picScale);
        uploadPictureResult.setPicFormat(imageInfo.getFormat());
        uploadPictureResult.setPicSize(FileUtil.size(file));
        //封装图片主色调
        uploadPictureResult.setPicColor(imageInfo.getAve());
        uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + uploadPath);
        return uploadPictureResult;
    }

    /**
     * 封装压缩后的图片和缩略图地址返回结果
     * @param originFilename 原始图片名
     * @param compressedCiObject 压缩图
     * @param thumbnailCiObject 缩略图
     * @param imageInfo 原始图的信息
     * @return 封装结果
     */
    private UploadPictureResult buildResult(String originFilename, CIObject compressedCiObject,CIObject thumbnailCiObject,ImageInfo imageInfo) {
        UploadPictureResult uploadPictureResult = new UploadPictureResult();
        int picWidth = compressedCiObject.getWidth();
        int picHeight = compressedCiObject.getHeight();
        double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();
        uploadPictureResult.setPicName(FileUtil.mainName(originFilename));
        uploadPictureResult.setPicWidth(picWidth);
        uploadPictureResult.setPicHeight(picHeight);
        uploadPictureResult.setPicScale(picScale);
        uploadPictureResult.setPicFormat(compressedCiObject.getFormat());
        uploadPictureResult.setPicSize(compressedCiObject.getSize().longValue());
        //设置图片主色调
        uploadPictureResult.setPicColor(imageInfo.getAve());
        // 设置图片为压缩后的地址（转为webp格式）
        uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + compressedCiObject.getKey());
        //设置图片缩放后的地址（宽高进行缩放）
        uploadPictureResult.setThumbnailUrl(cosClientConfig.getHost() + "/" + thumbnailCiObject.getKey());
        return uploadPictureResult;
    }
    /**
     * 删除临时文件
     */
    public void deleteTempFile(File file) {
        if (file == null) {
            return;
        }
        // 删除临时文件
        boolean deleteResult = file.delete();
        if (!deleteResult) {
            log.error("file delete error, filepath = {}", file.getAbsolutePath());
        }
    }

    /**
     * 上传图片
     * @param inputSource
     * @param uploadPathPrefix
     * @return
     * @param <T>
     */
    public <T> UploadPictureResult fileUploadPicture(T inputSource, String uploadPathPrefix) {
        //1. 校验图片
        validPicture(inputSource);
        //2.获取原始图片名
        String originFilename = getFileName(inputSource);

        String uuid = RandomStringUtils.randomAlphanumeric(10);
        //文件路径
        String uploadName = String.format("%s_%s.%s", DateUtil.formatDate(new Date()), uuid,
                FileUtil.getSuffix(originFilename));
        String uploadPath = String.format("/%s/%s", uploadPathPrefix, uploadName);
        File file = null;
        try {
            //3.创建临时文件
            file = File.createTempFile(uploadPath, null);
            //4.图片写入文件
            getFile(inputSource, file);
            //5.上传文件到COS
            PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, file);
            //拿到原图信息
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
            //拿到处理后图片信息
            ProcessResults processResults = putObjectResult.getCiUploadResult().getProcessResults();
            //集合中装的就是处理后的图片信息，每一个规则对应一个图片
            List<CIObject> objectList = processResults.getObjectList();
            CIObject thumbnailCIObject = null;
            if(CollUtil.isNotEmpty(objectList)){
                if(StrUtil.isBlank(objectList.get(0).getLocation()) && StrUtil.isBlank(objectList.get(1).getLocation())){
                    log.error("压缩和缩略都失败了，上传原始图片");
                    return buildResult(originFilename,file, uploadPath, imageInfo);
                }
                CIObject compressedCiObject = null;
                if(StrUtil.isNotBlank(objectList.get(0).getLocation())){
                    //压缩成功
                    compressedCiObject = objectList.get(0);
                }
                //缩略图的路径就是压缩图的路径，防止没有缩略图或者缩略失败
                thumbnailCIObject = compressedCiObject;
                if(objectList.size() > 1 && StrUtil.isNotBlank(objectList.get(1).getLocation())){
                    //缩略成功
                    thumbnailCIObject = objectList.get(1);
                }
                //删除原对象
                cosManager.deleteObject(uploadPath);
                log.info("删除原对象成功："+uploadPath);
                return buildResult(originFilename, compressedCiObject,thumbnailCIObject,imageInfo);
            }
            //6.封装最原始的图返回结果
            return buildResult(originFilename,file, uploadPath, imageInfo);
        } catch (IOException e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建临时文件失败");
        } finally {
            //7.删除文件
             this.deleteTempFile(file);
        }
    }
}
